package com.cqjtu.eecs.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.cqjtu.eecs.entity.*;
import com.cqjtu.eecs.entity.dto.*;
import com.cqjtu.eecs.exception.NotFoundException;
import com.cqjtu.eecs.service.*;
import com.cqjtu.eecs.utils.Assert;
import com.cqjtu.eecs.utils.listener.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: 文件 服务实现类
 * @author: 徐文升
 * @create: 2022-03-01 14:04
 **/

@Service
@Slf4j
public class FileServiceImpl implements IFileService{

    @Autowired
    private ITrainingProjectService trainingProjectService;
    @Autowired
    private ITrainingGoalBriefEntityService trainingGoalBriefEntityService;
    @Autowired
    private IGraduateRequirementTemplateService graduateRequirementTemplateService;
    @Autowired
    ITrainingGoalTemplateService trainingGoalTemplateService;
    @Autowired
    private IGraduateRequirementTrainingGoalTemplateService graduateRequirementTrainingGoalTemplateService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private ITrainingProjectCourseService trainingProjectCourseService;
    @Autowired
    private ICourseBackGraduateRequirementTemplateService courseBackGraduateRequirementTemplateService;
    @Autowired
    private ICourseService courseService;
    @Autowired
    private IProjectService projectService;
    @Autowired
    private IProjectCourseService projectCourseService;
    @Autowired
    private IRequirementService requirementService;
    @Autowired
    private ICourseRequirementService courseRequirementService;
    @Autowired
    private ICourseGoalService courseGoalService;
    @Autowired
    private IAssessmentLinkService assessmentLinkService;
    @Autowired
    private ICourseGoalAssessService courseGoalAssessService;

    /**
     * 处理excel文件
     * @param file
     * @return
     */
    public Boolean uploadTrainingProject(MultipartFile file) throws IOException {
        InputStream in = file.getInputStream();
        ExcelReader excelReader =
                EasyExcel.read(in).build();
        // 每个sheet分别创建监听器
        // 读取sheet0并存入数据库
        TrainingProjectListener trainingProjectListener = new TrainingProjectListener(trainingProjectService, trainingGoalBriefEntityService);
        ReadSheet sheet0 = EasyExcel.readSheet(0).head(TrainingProjectDTO.class).registerReadListener(trainingProjectListener).build();
        excelReader.read(sheet0);

        // 获取sheet1中读取的版本编号和专业代码，读取后续几个sheet时存入数据库需要
        List<TrainingProjectDTO> list = trainingProjectListener.getList();
        //专业代码
        String majorCode = list.get(0).getMajorCode();
        // 版本编号
        String versionCode = list.get(0).getVersionCode();

        //sheet1
        TrainingGoalListener trainingGoalListener =
                new TrainingGoalListener(majorCode,
                        versionCode, trainingGoalTemplateService);
        ReadSheet sheet1 = EasyExcel.readSheet(1).head(TrainingGoalDTO.class).registerReadListener(trainingGoalListener).build();

        // sheet2
        GraduateRequirementListener graduateRequirementListener =
                new GraduateRequirementListener(versionCode, majorCode, graduateRequirementTemplateService);
        ReadSheet sheet2 = EasyExcel.readSheet(2).head(GraduateRequirementTemplateDTO.class).registerReadListener(graduateRequirementListener).build();

        // sheet3
        GraduateRequirementTrainingGoalTemplateListener graduateRequirementTrainingGoalTemplateListener = new GraduateRequirementTrainingGoalTemplateListener(trainingGoalTemplateService,
                graduateRequirementTemplateService,
                graduateRequirementTrainingGoalTemplateService,
                list.get(0));
        ReadSheet sheet3 = EasyExcel.readSheet(3).head(GraduateRequirementTrainingGoalTemplateDTO.class).registerReadListener(graduateRequirementTrainingGoalTemplateListener).build();

        //sheet4
        TrainingProjectCourseListener trainingProjectCourseListener = new TrainingProjectCourseListener(majorCode, versionCode,
                courseTypeService, trainingProjectCourseService, courseService);
        ReadSheet sheet4 = EasyExcel.readSheet(4).head(TrainingProjectCourseDto.class).registerReadListener(trainingProjectCourseListener).build();

        // sheet5
        CourseBackGraduateRequirementTemplateListener courseBackGraduateRequirementTemplateListener = new CourseBackGraduateRequirementTemplateListener(
                versionCode,
                majorCode,
                courseBackGraduateRequirementTemplateService,
                courseService,
                graduateRequirementTemplateService);
        ReadSheet sheet5 = EasyExcel.readSheet(5).head(CourseBackGraduateRequirementTemplateDTO.class).registerReadListener(courseBackGraduateRequirementTemplateListener).build();

        // 一并读取sheet1-5
        excelReader.read(sheet1,sheet2,sheet3,sheet4,sheet5);

        // 这里千万别忘记关闭，读的时候会创建临时文件，到时磁盘会崩的
        excelReader.finish();
        in.close();

        return true;
    }

    /**
     * 上传课程大纲的excel文件
     * @param file
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean uploadCourseOutline(MultipartFile file) throws IOException {
        // 创建工作薄对象
        XSSFWorkbook sheets = new XSSFWorkbook(file.getInputStream());
        // 获取总的sheet数，应为3
        int numberOfSheets = sheets.getNumberOfSheets();
        if (numberOfSheets != 3)
            return false;
        // 分别处理工作薄
        XSSFSheet sheet = sheets.getSheetAt(0);
        // 获取行数，从0开始
        int lastRowNum = sheet.getLastRowNum();
        // 数据从第一行开始
        String majorCode = sheet.getRow(1).getCell(0).toString();
//        String majorName = sheet.getRow(1).getCell(1).toString();
        Integer grade = (int)Float.parseFloat(sheet.getRow(1).getCell(2).toString());
//        String courseCode = sheet.getRow(1).getCell(3).toString();
        String courseName = sheet.getRow(1).getCell(4).toString();
        // 根据专业代码和年级获取对应的方案
        // 第三行到最后一行都是课程目标和对应的毕业要求支撑
        Project project = projectService.getOne(new LambdaQueryWrapper<Project>()
                .eq(Project::getGrade, grade)
                .eq(Project::getMajorCode, majorCode)
        );
        Assert.notNull(project, new NotFoundException("Not find the project")); // 未找到抛出异常
        // 根据课程名找课程id
        Course course = courseService.selectCourseByCourseName(courseName.replaceAll(" ", ""));
        Assert.notNull(course, new NotFoundException("Not find the course"));
        // 找对应的课程-方案
        ProjectCourse projectCourse = projectCourseService.getOne(new LambdaQueryWrapper<ProjectCourse>()
                .eq(ProjectCourse::getCourseId, course.getCourseId())
                .eq(ProjectCourse::getPid, project.getPid())
        );
        Assert.notNull(projectCourse, new NotFoundException("Not find the projectCourse"));
        // 获取毕业要求id
        List<Requirement> requirementList = requirementService
                .list(new LambdaQueryWrapper<Requirement>().eq(Requirement::getPid, project.getPid()));
        // 将要求编码映射到要求id
        Map<String, Integer> map = requirementList
                .stream().collect(Collectors.toMap(Requirement::getRequirementCode, Requirement::getRequirementId));
//        requirementList.stream().collect(Collectors.toMap(Requirement::getRequirementCode, Req))
        new CourseGoal();
        // 获取已有的对应的权重
        List<CourseRequirement> courseRequirements = courseRequirementService.list(new LambdaQueryWrapper<CourseRequirement>()
                .eq(CourseRequirement::getProjectCourseId, projectCourse.getProjectCourseId()));
        if (courseRequirements.isEmpty())
            throw new NotFoundException("Not find the courseRequirements");
        Map<Integer, Float> map1 = courseRequirements.stream()
                .collect(Collectors.toMap(CourseRequirement::getRequirementId, CourseRequirement::getBackWeight));
        List<CourseGoal> courseGoals = new ArrayList<>();
        for (int i=3;i<=lastRowNum;i++){
            courseGoals.add(            new CourseGoal(null, map.get(sheet.getRow(i).getCell(2).toString()),
                    projectCourse.getProjectCourseId(), sheet.getRow(i).getCell(0).toString(),
                    sheet.getRow(i).getCell(1).toString(),map1.get(map.get(sheet.getRow(i).getCell(2).toString()))
            ));
        }
        if (!courseGoalService.saveBatch(courseGoals))
            return false;
        // 处理sheet2
        sheet = sheets.getSheetAt(1);
        List<AssessmentLink> assessmentLinks = new ArrayList<>();
        lastRowNum = sheet.getLastRowNum();
        for (int i = 1; i <= lastRowNum; i++) {
            if (sheet.getRow(i).getCell(0).getCellType() != CellType.BLANK){
                assessmentLinks.add(new AssessmentLink(null, projectCourse.getProjectCourseId(),
                        sheet.getRow(i).getCell(0).toString(),
                        Float.parseFloat(sheet.getRow(i).getCell(1).toString())
                ));

            }
        }
//        System.out.println(assessmentLinks);
        if (!assessmentLinkService.saveBatch(assessmentLinks))
            return false;
        // 处理sheet3
        sheet = sheets.getSheetAt(2);
        // 获取已插入的考核环节
        List<AssessmentLink> assessmentLinkList = assessmentLinkService
                .list(new LambdaQueryWrapper<AssessmentLink>()
                .eq(AssessmentLink::getProjectCourseId, projectCourse.getProjectCourseId()));
        // 环节名映射到环节id
        Map<String, Integer> collect = assessmentLinkList.stream()
                .collect(Collectors.toMap(AssessmentLink::getLinkName, AssessmentLink::getLinkId));
        // 获取已插入的课程目标
        List<CourseGoal> courseGoalList = courseGoalService.list(new LambdaQueryWrapper<CourseGoal>()
                .eq(CourseGoal::getProjectCourseId, projectCourse.getProjectCourseId()));
        // 课程目标名映射到课程目标id
        Map<String, Integer> collect1 = courseGoalList.stream()
                .collect(Collectors.toMap(CourseGoal::getCourseGoalName, CourseGoal::getCourseGoalId));
        ArrayList<CourseGoalAssess> courseGoalAssesses = new ArrayList<>();
        lastRowNum = sheet.getLastRowNum();
        int maxCol = sheet.getRow(0).getLastCellNum();
        for (int i=1;i<=lastRowNum;i++){
            for (int j = 1; j < maxCol; j++){
                try {
                    if (sheet.getRow(i).getCell(j).getCellType() != CellType.BLANK){
//                        System.out.println(Float.parseFloat(sheet.getRow(i).getCell(j).toString()));
                        courseGoalAssesses.add(new CourseGoalAssess(
                                collect.get(sheet.getRow(0).getCell(j).toString()),
                                collect1.get(sheet.getRow(i).getCell(0).toString()),
                                Float.parseFloat(sheet.getRow(i).getCell(j).toString())
                        ));
                    }
                }catch (NullPointerException e){
                    log.info("第{}行第{}列为空",i,j);
//                    System.out.println("第"+i+"行,第"+j+"列为空");
                }
            }
        }
//        System.out.println(courseGoalAssesses);
        if (!courseGoalAssessService.saveBatch(courseGoalAssesses))
            return false;
        return true;
    }
}
